package cn.com.dstz.filter;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;
import java.util.Map;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.commons.lang.StringUtils;

import cn.com.dstz.utils.RequestUtils;
import cn.com.dstz.web.constants.Constants;

/**
 * 后台管理Filter
 * @author 叶装装
 * @since 1.6
 * 
 * 	--------------------------------------------------------------------
 * 1. 修改了权限判断的方式
 * 2. 修改了struts.xml，增加了更精准的namespace
 * ---------------------------------------------------------------------
 * 1. 在namespace为admin的配置下，只是判断当前是否已有登录用户，如果没有，将不具备访问权限
 * 2. 在namespace为admin/*的配置下，继承了1中的权限，并且，它会判断请求的路径是否不用过滤，如果是则返回真，如果不是，进入权限判断的
 */
public class AdminFilter implements Filter{

	private String contextPath;
	private String regex;
	
	public void destroy( ) {
		regex = null;
		contextPath = null;
	}

	public void doFilter( ServletRequest request, ServletResponse response, FilterChain chain ) throws IOException, ServletException {
		HttpServletRequest httpReq = ( HttpServletRequest ) request;
		HttpServletResponse httpRes = ( HttpServletResponse ) response;
		contextPath = httpReq.getContextPath( );
		
		HttpSession session = RequestUtils.getSession( httpReq );
	
		Map< String, Object > admin = RequestUtils.getEntityInSession( Constants.ADMIN_IN_SESSION, session );
	
		if( admin == null || admin.isEmpty( ) ){
			redirect( httpRes, httpReq );
			return;
		}
		String requestURI = httpReq.getRequestURI( );
		int jsessionid = requestURI.lastIndexOf( ";jsessionid" );
		
		if( jsessionid != -1 ){
			requestURI = requestURI.substring( 0, jsessionid );
		}
		
		boolean hasAccess = hasAccess( requestURI, httpReq );
		if( !hasAccess ){
			response( httpRes, httpReq );
			return;
		}
		
		chain.doFilter( httpReq, httpRes );
		
	}
	
	private void response( HttpServletResponse httpRes, HttpServletRequest httpReq ) throws IOException{;
		httpRes.setCharacterEncoding("GBK");
		String requestType = httpReq.getHeader("X-Requested-With");
		String msg = "拒绝访问";
		if( "XMLHttpRequest".equals( requestType )){
			msg = "-99";
		}
		PrintWriter out = httpRes.getWriter();
		out.write( msg );
		out.flush();
		out.close();
	}
	
	private boolean hasAccess( String requestURI, HttpServletRequest httpReq ){

		if( StringUtils.isNotBlank( requestURI ) ){
			if( isNotFilterURL( requestURI ) ){
				return true;
			}
			
			List< Map< String, Object >> purviewList = RequestUtils.getEntityInSession( Constants.ADMIN_PURVIEW, RequestUtils.getSession( httpReq ) );
			
			for( Map< String, Object > purview : purviewList ){
				Object url = purview.get( "url" );
				if( StringUtils.equals( contextPath + url, requestURI )){
					return true;
				}
			}
		}
		
		return false;
	}
	
	public void init( FilterConfig filterConfig ) throws ServletException {
		regex = StringUtils.trimToEmpty( filterConfig.getInitParameter( "regex" ) );
	}
	
	private void redirect( HttpServletResponse response, HttpServletRequest request ){
		try{
			response.sendRedirect( request.getContextPath( ) +  "/login.jsp" );
		}catch( IOException e ){
			e.printStackTrace();
		}
	}
	private boolean isNotFilterURL( String requestURI ){
		requestURI = requestURI.substring( contextPath.length( ), requestURI.length( ) );
		return requestURI.matches( regex );
	}

}
